package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"time"

	"goVector/pkg/api"
	"goVector/pkg/config"
	"goVector/pkg/db"
	"goVector/pkg/embedding"

	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
)

func main() {
	// 加载配置
	cfg, err := config.LoadConfig()
	if err != nil {
		log.Printf("加载配置失败: %v，将使用默认配置", err)
		cfg = config.DefaultConfig()
	}

	// 配置日志
	log.SetFlags(log.LstdFlags | log.Lshortfile)

	// 设置Gin模式
	if cfg.Server.Debug {
		gin.SetMode(gin.DebugMode)
	} else {
		gin.SetMode(gin.ReleaseMode)
	}

	// 创建Gin引擎
	r := gin.Default()

	// 启用CORS
	if cfg.Server.CORS {
		config := cors.DefaultConfig()
		config.AllowAllOrigins = true
		config.AllowMethods = []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}
		config.AllowHeaders = []string{"Origin", "Content-Length", "Content-Type", "Authorization"}
		r.Use(cors.New(config))
	}

	// 创建嵌入服务
	var embedder embedding.Embedder
	if cfg.Embedding.Provider == "ollama" {
		embedder = embedding.NewOllamaEmbedder(embedding.OllamaConfig{
			Host:  cfg.Embedding.Ollama.Host,
			Port:  cfg.Embedding.Ollama.Port,
			Model: cfg.Embedding.Ollama.Model,
		})
	} else {
		log.Fatalf("不支持的嵌入服务提供商: %s", cfg.Embedding.Provider)
	}

	var vectorServer *api.VectorServer

	// 根据配置选择数据库模式
	if cfg.Database.MemoryMode {
		// 内存模式
		vectorDB, err := db.NewSQLiteVectorDB(":memory:")
		if err != nil {
			log.Fatalf("创建内存数据库失败: %v", err)
		}
		if err := vectorDB.InitDB(); err != nil {
			log.Fatalf("初始化数据库失败: %v", err)
		}
		vectorServer = api.NewVectorServer(vectorDB, embedder)
		log.Printf("使用内存数据库模式")
	} else {
		// 选择是否使用集合模式
		if cfg.Database.UseCollections {
			// 确保集合目录是绝对路径
			if !filepath.IsAbs(cfg.Database.CollectionsDir) {
				absPath, err := filepath.Abs(cfg.Database.CollectionsDir)
				if err != nil {
					log.Printf("警告: 无法获取集合目录的绝对路径: %v", err)
					absPath = filepath.Join(".", cfg.Database.CollectionsDir)
				}
				cfg.Database.CollectionsDir = absPath
			}

			// 确保目录存在
			if err := os.MkdirAll(cfg.Database.CollectionsDir, 0755); err != nil {
				log.Fatalf("创建集合目录失败: %v", err)
			}

			// 创建集合管理器
			collectionMgr := db.NewCollectionManager(cfg.Database.CollectionsDir)
			vectorServer = api.NewVectorServerWithCollections(collectionMgr, embedder)

			log.Printf("使用集合模式, 目录: %s", cfg.Database.CollectionsDir)
		} else {
			// 使用单一数据库文件
			if !filepath.IsAbs(cfg.Database.SingleDBPath) {
				absPath, err := filepath.Abs(cfg.Database.SingleDBPath)
				if err != nil {
					log.Printf("警告: 无法获取数据库文件的绝对路径: %v", err)
					absPath = filepath.Join(".", cfg.Database.SingleDBPath)
				}
				cfg.Database.SingleDBPath = absPath
			}

			vectorDB, err := db.NewSQLiteVectorDB(cfg.Database.SingleDBPath)
			if err != nil {
				log.Fatalf("创建数据库失败: %v", err)
			}
			if err := vectorDB.InitDB(); err != nil {
				log.Fatalf("初始化数据库失败: %v", err)
			}
			vectorServer = api.NewVectorServer(vectorDB, embedder)

			log.Printf("使用单一数据库文件: %s", cfg.Database.SingleDBPath)
		}
	}

	// 设置路由
	apiRouter := r.Group("/")
	vectorServer.SetupRoutes(apiRouter)

	// 添加健康检查接口
	r.GET("/health", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"status": "healthy",
			"model":  cfg.Embedding.Ollama.Model,
		})
	})

	// 设置静态文件服务
	if cfg.Web.ServeStatic {
		r.Static("/web", cfg.Web.StaticDir)

		// 设置默认页面
		if cfg.Web.RedirectRoot {
			r.GET("/", func(c *gin.Context) {
				c.Redirect(http.StatusMovedPermanently, "/web/index.html")
			})
		}
	}

	// 创建HTTP服务器
	addr := fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port)
	srv := &http.Server{
		Addr:    addr,
		Handler: r,
	}

	// 在单独的协程中启动服务器
	go func() {
		log.Printf("服务器启动，监听地址: %s", addr)
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("服务器启动失败: %v", err)
		}
	}()

	// 创建一个通道来等待中断信号
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	log.Println("收到关闭信号，开始优雅关闭...")

	// 设置超时上下文用于关闭服务器
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	// 关闭HTTP服务器
	if err := srv.Shutdown(ctx); err != nil {
		log.Fatalf("服务器关闭出错: %v", err)
	}

	// 调用 VectorServer 的 Shutdown 方法保存数据
	if err := vectorServer.Shutdown(); err != nil {
		log.Fatalf("数据保存失败: %v", err)
	}

	log.Println("服务器已安全关闭，数据已保存")
}
